﻿Imports System
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities
    <ComVisible(False)> _
    Public Class StateActivityValidator
        Inherits CompositeActivityValidator
        ' Methods
        Public Overrides Function Validate(ByVal manager As ValidationManager, ByVal obj As Object) As ValidationErrorCollection
            Dim validationErrors As New ValidationErrorCollection(MyBase.Validate(manager, obj))
            Dim state As StateActivity = [TryCast](obj,StateActivity)
            If (state Is Nothing) Then
                Throw New ArgumentException(SR.GetString("Error_UnexpectedArgumentType", New Object() { GetType(StateActivity).FullName }), "obj")
            End If
            If (Not state.Parent Is Nothing) Then
                If StateMachineHelpers.IsStateMachine(state) Then
                    validationErrors.Add(New ValidationError(SR.GetError_StateMachineWorkflowMustBeARootActivity, &H621))
                    Return validationErrors
                End If
                If Not TypeOf state.Parent Is StateActivity Then
                    validationErrors.Add(New ValidationError(SR.GetError_InvalidStateActivityParent, &H62B))
                    Return validationErrors
                End If
            End If
            If ((state.Parent Is Nothing) AndAlso Not StateMachineHelpers.IsStateMachine(state)) Then
                StateActivityValidator.ValidateCustomStateActivity(state, validationErrors)
            End If
            If StateMachineHelpers.IsLeafState(state) Then
                StateActivityValidator.ValidateLeafState(state, validationErrors)
            ElseIf StateMachineHelpers.IsRootState(state) Then
                StateActivityValidator.ValidateRootState(state, validationErrors)
            Else
                StateActivityValidator.ValidateState(state, validationErrors)
            End If
            StateActivityValidator.ValidateEventDrivenActivities(state, validationErrors)
            Return validationErrors
        End Function

        Public Overrides Function ValidateActivityChange(ByVal activity As Activity, ByVal action As ActivityChangeAction) As ValidationError
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            If (action Is Nothing) Then
                Throw New ArgumentNullException("action")
            End If
            If (((activity.ExecutionStatus <> ActivityExecutionStatus.Initialized) AndAlso (activity.ExecutionStatus <> ActivityExecutionStatus.Executing)) AndAlso (activity.ExecutionStatus <> ActivityExecutionStatus.Closed)) Then
                Return New ValidationError(SR.GetString("Error_DynamicActivity2", New Object() { activity.QualifiedName, activity.ExecutionStatus, activity.GetType.FullName }), &H50F)
            End If
            Dim action2 As RemovedActivityAction = [TryCast](action,RemovedActivityAction)
            If (Not action2 Is Nothing) Then
                Dim originalRemovedActivity As StateActivity = [TryCast](action2.OriginalRemovedActivity,StateActivity)
                If (Not originalRemovedActivity Is Nothing) Then
                    Return New ValidationError(SR.GetError_CantRemoveState(originalRemovedActivity.QualifiedName), &H61B)
                End If
                If (activity.ExecutionStatus = ActivityExecutionStatus.Executing) Then
                    Dim activity3 As EventDrivenActivity = [TryCast](action2.OriginalRemovedActivity,EventDrivenActivity)
                    If (Not activity3 Is Nothing) Then
                        Return New ValidationError(SR.GetError_CantRemoveEventDrivenFromExecutingState(activity3.QualifiedName, activity.QualifiedName), &H620)
                    End If
                End If
            End If
            Return Nothing
        End Function

        Private Shared Sub ValidateCompletedState(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            Dim completedStateName As String = StateMachineHelpers.GetCompletedStateName(state)
            If Not String.IsNullOrEmpty(completedStateName) Then
                Dim activity As StateActivity = StateMachineHelpers.FindStateByName(state, completedStateName)
                If (activity Is Nothing) Then
                    validationErrors.Add(New ValidationError(SR.GetError_CompletedStateMustPointToAState, &H5F6, False, "CompletedStateName"))
                ElseIf StateMachineHelpers.IsLeafState(activity) Then
                    If (activity.EnabledActivities.Count > 0) Then
                        validationErrors.Add(New ValidationError(SR.GetString("Error_CompletedStateCannotContainActivities"), &H5FF, False, "CompletedStateName"))
                    End If
                Else
                    validationErrors.Add(New ValidationError(SR.GetError_CompletedStateMustPointToALeafNodeState, &H5F8, False, "CompletedStateName"))
                End If
            End If
        End Sub

        Private Shared Sub ValidateCompositeStateChildren(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            Dim flag As Boolean = False
            Dim activity As Activity
            For Each activity In state.Activities
                If ((activity.Enabled AndAlso Not TypeOf activity Is EventDrivenActivity) AndAlso Not TypeOf activity Is StateActivity) Then
                    flag = True
                    Exit For
                End If
            Next
            If flag Then
                validationErrors.Add(New ValidationError(SR.GetError_InvalidCompositeStateChild, &H5F0))
            End If
        End Sub

        Private Shared Sub ValidateCustomStateActivity(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            If (state.Activities.Count > 0) Then
                validationErrors.Add(New ValidationError(SR.GetError_BlackBoxCustomStateNotSupported, &H623))
            End If
        End Sub

        Private Shared Sub ValidateEventDrivenActivities(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            Dim list As New List([Of] EventDrivenActivity)
            Dim activity As Activity
            For Each activity In state.EnabledActivities
                Dim item As EventDrivenActivity = [TryCast](activity,EventDrivenActivity)
                If (Not item Is Nothing) Then
                    list.Add(item)
                End If
            Next
            Dim activity3 As EventDrivenActivity
            For Each activity3 In list
                If Not StateActivityValidator.ValidateMultipleIEventActivity(activity3, validationErrors) Then
                    Exit For
                End If
            Next
        End Sub

        Private Shared Sub ValidateInitialState(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            Dim initialStateName As String = StateMachineHelpers.GetInitialStateName(state)
            If String.IsNullOrEmpty(initialStateName) Then
                If (state.Activities.Count > 0) Then
                    validationErrors.Add(New ValidationError(SR.GetString("Error_PropertyNotSet", New Object() { "InitialStateName" }), &H116, False, "InitialStateName"))
                End If
            Else
                Dim activity As StateActivity = StateMachineHelpers.FindStateByName(state, initialStateName)
                If (activity Is Nothing) Then
                    validationErrors.Add(New ValidationError(SR.GetError_InitialStateMustPointToAState, &H5F5, False, "InitialStateName"))
                Else
                    If Not StateMachineHelpers.IsLeafState(activity) Then
                        validationErrors.Add(New ValidationError(SR.GetError_InitialStateMustPointToALeafNodeState, &H5F7, False, "InitialStateName"))
                    End If
                    Dim completedStateName As String = StateMachineHelpers.GetCompletedStateName(state)
                    If (initialStateName = completedStateName) Then
                        validationErrors.Add(New ValidationError(SR.GetError_InitialStateMustBeDifferentThanCompletedState, &H62C, False, "InitialStateName"))
                    End If
                End If
            End If
        End Sub

        Private Shared Sub ValidateLeafState(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            StateActivityValidator.ValidateLeafStateChildren(state, validationErrors)
        End Sub

        Private Shared Sub ValidateLeafStateChildren(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            Dim flag As Boolean = False
            Dim activity As Activity
            For Each activity In state.Activities
                If ((activity.Enabled AndAlso Not TypeOf activity Is EventDrivenActivity) AndAlso (Not TypeOf activity Is StateInitializationActivity AndAlso Not TypeOf activity Is StateFinalizationActivity)) Then
                    flag = True
                    Exit For
                End If
            Next
            If flag Then
                validationErrors.Add(New ValidationError(SR.GetError_InvalidLeafStateChild, &H5F1))
            End If
        End Sub

        Private Shared Function ValidateMultipleIEventActivity(ByVal eventDriven As EventDrivenActivity, ByVal validationErrors As ValidationErrorCollection) As Boolean
            Dim firstEventActivity As IEventActivity = Nothing
            If (eventDriven.EnabledActivities.Count > 0) Then
                firstEventActivity = [TryCast](eventDriven.EnabledActivities.Item(0),IEventActivity)
            End If
            Return StateActivityValidator.ValidateMultipleIEventActivityInCompositeActivity(eventDriven, firstEventActivity, eventDriven, validationErrors)
        End Function

        Private Shared Function ValidateMultipleIEventActivityInCompositeActivity(ByVal eventDriven As EventDrivenActivity, ByVal firstEventActivity As IEventActivity, ByVal parent As CompositeActivity, ByVal validationErrors As ValidationErrorCollection) As Boolean
            Dim activity As Activity
            For Each activity In parent.Activities
                If (activity.Enabled AndAlso (Not activity Is firstEventActivity)) Then
                    If TypeOf activity Is IEventActivity Then
                        validationErrors.Add(New ValidationError(SR.GetString("Error_EventDrivenMultipleEventActivity", New Object() { eventDriven.Name, GetType(IEventActivity).FullName, GetType(EventDrivenActivity).Name }), &H524))
                        Return False
                    End If
                    Dim activity2 As CompositeActivity = [TryCast](activity,CompositeActivity)
                    If ((Not activity2 Is Nothing) AndAlso Not StateActivityValidator.ValidateMultipleIEventActivityInCompositeActivity(eventDriven, firstEventActivity, activity2, validationErrors)) Then
                        Return False
                    End If
                End If
            Next
            Return True
        End Function

        Private Shared Sub ValidateRootState(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            StateActivityValidator.ValidateCompositeStateChildren(state, validationErrors)
            If StateMachineHelpers.IsStateMachine(state) Then
                StateActivityValidator.ValidateInitialState(state, validationErrors)
                StateActivityValidator.ValidateCompletedState(state, validationErrors)
            End If
        End Sub

        Private Shared Sub ValidateState(ByVal state As StateActivity, ByVal validationErrors As ValidationErrorCollection)
            StateActivityValidator.ValidateCompositeStateChildren(state, validationErrors)
        End Sub

    End Class
End Namespace

